home *** CD-ROM | disk | FTP | other *** search
- //***************************************************************************
- //
- // this file is (c) '94-'96 Niklas Beisert
- //
- // this file is part of the cubic player development kit.
- // you may only use/modify/spread this file under the terms stated
- // in the cubic player development kit accompanying documentation.
- //
- //***************************************************************************
-
- //[sound]
- // playerdevices=devpWSS devpGUS devpSB devpPAS devpNone devpDisk
- //[devwGUS]
- // link=devwgus
- // driver=_mcpUltraSound
- // addprocs=_mcpGUSAdd
- // handle=2
- // gusSlowUpload=on
- // gusSystemTimer=on
-
-
-
- // wavetable device example
-
- #include <time.h>
- #include <string.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "ss.h"
- #include "mcp.h"
- #include "mix.h"
- #include "irq.h"
- #include "dma.h"
- #include "timer.h"
-
- #define MAXSAMPLES 256
-
- #define SS_GUS_SLOWUPLOAD 1
- #define SS_GUS_SYSTIMER 2
-
- extern "C" extern sounddevice mcpUltraSound;
-
- static unsigned short gusPort;
- static unsigned char gusDMA;
- static unsigned char gusIRQ;
- static unsigned char gusDMA2;
- static unsigned char gusIRQ2;
- static unsigned long gusMem;
- static unsigned char activevoices;
-
-
- unsigned long muldiv64(unsigned long, unsigned long, unsigned long);
- //#pragma aux muldiv64 parm [eax] [edx] [ecx] = "mul edx" "div ecx"
- #pragma aux muldiv64 parm [eax] [edx] [ecx] modify [ebx] = "mul edx" "mov ebx,ecx" "shr ebx,1" "add eax,ebx" "adc edx,0" "div ecx"
-
- static char getcfg()
- {
- char *ptr=getenv("ULTRASND");
- if (!ptr)
- return 0;
- while (isspace(*ptr))
- ptr++;
- if (!ptr)
- return 0;
- gusPort=strtoul(ptr, 0, 16);
- while ((*ptr!=',')&&*ptr)
- ptr++;
- if (!*ptr++)
- return 0;
- gusDMA=strtoul(ptr, 0, 10)&7;
- while ((*ptr!=',')&&*ptr)
- ptr++;
- if (!*ptr++)
- return 0;
- gusDMA2=strtoul(ptr, 0, 10)&7;
- while ((*ptr!=',')&&*ptr)
- ptr++;
- if (!*ptr++)
- return 0;
- gusIRQ=strtoul(ptr, 0, 10)&15;
- while ((*ptr!=',')&&*ptr)
- ptr++;
- if (!*ptr++)
- return 0;
- gusIRQ2=strtoul(ptr, 0, 10)&15;
- return 1;
- }
-
- static unsigned char inpGUS(unsigned short p)
- {
- return inp(gusPort+p);
- }
-
- static unsigned short inpwGUS(unsigned short p)
- {
- return inpw(gusPort+p);
- }
-
- static void delayGUS()
- {
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- inp(gusPort+0x107);
- }
-
- static void outpGUS(unsigned short p, unsigned char v)
- {
- outp(gusPort+p,v);
- }
-
- static void outpwGUS(unsigned short p, unsigned short v)
- {
- outpw(gusPort+p,v);
- }
-
- static void outGUS(unsigned char c, unsigned char v)
- {
- outp(gusPort+0x103, c);
- outp(gusPort+0x105, v);
- }
-
- static void outdGUS(unsigned char c, unsigned char v)
- {
- outp(gusPort+0x103, c);
- outp(gusPort+0x105, v);
- delayGUS();
- outp(gusPort+0x105, v);
- }
-
- static void outwGUS(unsigned char c, unsigned short v)
- {
- outp(gusPort+0x103, c);
- outpw(gusPort+0x104, v);
- }
-
- static unsigned char inGUS(unsigned char c)
- {
- outp(gusPort+0x103, c);
- return inp(gusPort+0x105);
- }
-
- static unsigned short inwGUS(unsigned char c)
- {
- outp(gusPort+0x103, c);
- return inpw(gusPort+0x104);
- }
-
- static inline void outpGUS0(unsigned char v)
- {
- outpGUS(0x00, v);
- }
-
- static inline void outpGUS8(unsigned char v)
- {
- outpGUS(0x08, v);
- }
-
- static inline void outpGUS9(unsigned char v)
- {
- outpGUS(0x09, v);
- }
-
- static inline void outpGUSB(unsigned char v)
- {
- outpGUS(0x0B, v);
- }
-
- static inline void outpGUSF(unsigned char v)
- {
- outpGUS(0x0F, v);
- }
-
- static inline unsigned char peekGUS(unsigned long adr)
- {
- outwGUS(0x43, adr);
- outdGUS(0x44, adr>>16);
- return inpGUS(0x107);
- }
-
- static inline void pokeGUS(unsigned long adr, unsigned char data)
- {
- outwGUS(0x43, adr);
- outdGUS(0x44, adr>>16);
- outpGUS(0x107, data);
- }
-
- static inline void selvoc(char ch)
- {
- outpGUS(0x102, ch);
- }
-
- static inline void setfreq(unsigned short frq)
- {
- outwGUS(0x01, frq&~1);
- }
-
- static inline void setvol(unsigned short vol)
- {
- outwGUS(0x09, vol<<4);
- }
-
- static inline unsigned short getvol()
- {
- return inwGUS(0x89)>>4;
- }
-
- static inline void setpan(unsigned char pan)
- {
- outGUS(0x0C, pan);
- }
-
- static inline void setpoint8(unsigned long p, unsigned char t)
- {
- t=(t==1)?0x02:(t==2)?0x04:0x0A;
- outwGUS(t, (p>>7)&0x1FFF);
- outwGUS(t+1, p<<9);
- }
-
- static inline unsigned long getpoint8(unsigned char t)
- {
- t=(t==1)?0x82:(t==2)?0x84:0x8A;
- return (inwGUS(t)<<16)|inwGUS(t+1);
- }
-
- static inline void setmode(unsigned char m)
- {
- outdGUS(0x00, m);
- }
-
- static inline unsigned char getmode()
- {
- return inGUS(0x80);
- }
-
- static inline void setvst(unsigned char s)
- {
- outGUS(0x07, s);
- }
-
- static inline void setvend(unsigned char s)
- {
- outGUS(0x08, s);
- }
-
- static inline void setvmode(unsigned char m)
- {
- outdGUS(0x0D, m);
- }
-
- static inline unsigned char getvmode()
- {
- return inGUS(0x8D);
- }
-
- static inline void settimer(unsigned char o)
- {
- outGUS(0x45, o);
- }
-
- static inline void settimerlen(unsigned char l)
- {
- outGUS(0x46, l);
- }
-
- static int testPort(unsigned short port)
- {
- gusPort=port;
-
- outGUS(0x4C, 0);
-
- delayGUS();
- delayGUS();
-
- outGUS(0x4C, 1);
-
- delayGUS();
- delayGUS();
-
- char v0=peekGUS(0);
- char v1=peekGUS(1);
-
- pokeGUS(0,0xAA);
- pokeGUS(1,0x55);
-
- char gus=peekGUS(0)==0xAA;
-
- pokeGUS(0,v0);
- pokeGUS(1,v1);
-
- if (!gus)
- return 0;
-
- int i,j;
- unsigned char oldmem[4];
- for (i=0; i<4; i++)
- oldmem[i]=peekGUS(i*256*1024);
-
- pokeGUS(0,1);
- pokeGUS(0,1);
- gusMem=256*1024;
- for (i=1; i<4; i++)
- {
- pokeGUS(i*256*1024, 15+i);
- pokeGUS(i*256*1024, 15+i);
- for (j=0; j<i; j++)
- {
- if (peekGUS(j*256*1024)!=(1+j))
- break;
- if (peekGUS(j*256*1024)!=(1+j))
- break;
- }
- if (j!=i)
- break;
- if (peekGUS(i*256*1024)!=(15+i))
- break;
- if (peekGUS(i*256*1024)!=(15+i))
- break;
- pokeGUS(i*256*1024, 1+i);
- pokeGUS(i*256*1024, 1+i);
- gusMem+=256*1024;
- }
-
- for (i=3; i>=0; i--)
- {
- pokeGUS(i*256*1024, oldmem[i]);
- pokeGUS(i*256*1024, oldmem[i]);
- }
-
- return 1;
- }
-
- static void initgus(char voices)
- {
- if (voices<14)
- voices=14;
- if (voices>32)
- voices=32;
-
- activevoices=voices;
-
- int i;
-
- outGUS(0x4C, 0);
- for (i=0; i<10; i++)
- delayGUS();
-
- outGUS(0x4C, 1);
- for (i=0; i<10; i++)
- delayGUS();
-
- outGUS(0x41, 0x00);
- outGUS(0x45, 0x00);
- outGUS(0x49, 0x00);
-
- outGUS(0xE, (voices-1)|0xC0);
-
- inpGUS(0x6);
- inGUS(0x41);
- inGUS(0x49);
- inGUS(0x8F);
-
- for (i=0; i<32; i++)
- {
- selvoc(i);
- setvol(0); // vol=0
- setmode(3); // stop voice
- setvmode(3); // stop volume
- setpoint8(0,0);
- outGUS(0x06, 63);
- delayGUS();
- }
-
- inpGUS(0x6);
- inGUS(0x41);
- inGUS(0x49);
- inGUS(0x8F);
-
- outGUS(0x4C,0x07);
- /*
- unsigned char l1="\x00\x00\x01\x03\x00\x02\x00\x04\x00\x00\x00\x05\x06\x00\x00\x07"[gusIRQ]|((gusIRQ==gusIRQ2)?0x40:"\x00\x00\x08\x18\x00\x10\x00\x20\x00\x00\x00\x28\x30\x00\x00\x38"[gusIRQ2]);
- unsigned char l2="\x00\x01\x00\x02\x00\x03\x04\x05"[gusDMA]|((gusDMA==gusDMA2)?0x40:"\x00\x08\x00\x10\x00\x18\x20\x28"[gusDMA2]);
-
- outpGUSF(5);
- outpGUS0(0x0B);
- outpGUSB(0);
- outpGUSF(0);
-
- outpGUS0(0x0B);
- outpGUSB(l2|0x80);
- outpGUS0(0x4B);
- outpGUSB(l1);
- outpGUS0(0x0B);
- outpGUSB(l2);
- outpGUS0(0x4B);
- outpGUSB(l1);
- */
- selvoc(0);
- outpGUS0(0x08);
- selvoc(0);
- /*
- outGUS(0x4C,0x01);
- settimer(0x00); // stop timer
- outpGUS8(0x04);
- outpGUS9(0x80);
- */
- }
-
-
-
- struct guschan
- {
- unsigned long startpos;
- unsigned long endpos;
- unsigned long loopstart;
- unsigned long loopend;
- unsigned long samprate;
- unsigned char redlev;
-
- unsigned short cursamp;
- unsigned char mode;
-
- unsigned short voll;
- unsigned short volr;
-
- unsigned char inited;
- signed char chstatus;
- signed short nextsample;
- signed long nextpos;
- unsigned char orgloop;
- signed char loopchange;
-
- unsigned long orgfreq;
- unsigned long orgdiv;
- unsigned short orgvol;
- signed short orgpan;
- unsigned char pause;
- unsigned char wasplaying;
-
- void *smpptr;
- };
-
- struct gussample
- {
- signed long pos;
- unsigned long length;
- unsigned long loopstart;
- unsigned long loopend;
- unsigned long samprate;
- int type;
- unsigned char redlev;
- void *ptr;
- };
-
- static unsigned short linvol[513];
- static unsigned long mempos;
- static gussample samples[MAXSAMPLES];
- static unsigned short samplenum;
-
- static unsigned char channelnum;
- static void (*playerproc)();
- static guschan channels[32];
- static unsigned long gtimerlen;
- static unsigned long gtimerpos;
- static unsigned long stimerlen;
- static unsigned long stimerpos;
- static char __far *stack;
- static const unsigned long stacksize=8192;
- static unsigned char stackused;
- static void __far *oldssesp;
- static unsigned short relspeed;
- static unsigned long orgspeed;
- static unsigned char mastervol;
- static signed char masterpan;
- static signed char masterbal;
- static unsigned short masterfreq;
- static unsigned long amplify;
-
- static unsigned char paused;
- static unsigned char doublechan;
-
- static __segment dmasel;
- static void *dmabuf;
- static int dmalen;
- static volatile unsigned char dmaactive;
- static void *dmaxfer;
- static unsigned long dmaleft;
- static unsigned long dmapos;
- static unsigned char dma16bit;
- static unsigned char doslowupload;
- static unsigned char usesystimer;
-
- static unsigned char filter;
-
-
- static void fadevol(unsigned short v)
- {
- unsigned short start=getvol();
- unsigned short end=v;
- unsigned char vmode;
- if (abs((short)(start-end))<64)
- {
- setvol(end);
- return;
- }
-
- if (start>end)
- {
- unsigned short t=start;
- start=end;
- end=t;
- vmode=0x40;
- }
- else
- vmode=0;
- if (start<64)
- start=64;
- if (end>4032)
- end=4032;
- setvst(start>>4);
- setvend(end>>4);
- setvmode(vmode);
- }
-
- static inline void fadevoldown()
- {
- setvst(0x04);
- setvend(0xFC);
- setvmode(0x40);
- }
-
-
- static void processtick()
- {
- int i;
-
- for (i=0; i<channelnum; i++)
- {
- guschan &c=channels[i];
- if (c.inited&&(c.chstatus||(c.nextpos!=-1)))
- {
- selvoc(i);
- setmode(c.mode|3);
- fadevoldown();
- }
-
- c.chstatus=0;
- }
-
- for (i=0; i<channelnum; i++)
- {
- selvoc(i);
- while (!(getvmode()&1));
- }
-
- for (i=0; i<channelnum; i++)
- {
- guschan &c=channels[i];
- selvoc(i);
- if (c.inited)
- {
- if (c.nextsample!=-1)
- {
- gussample &s=samples[c.nextsample];
- unsigned char bit16=!!(s.type&mcpSamp16Bit);
- c.startpos=s.pos;
- if (bit16)
- c.startpos=(c.startpos&0xC0000)|((c.startpos>>1)&0x1FFFF)|0x20000;
- c.endpos=c.startpos+s.length;
- c.loopstart=c.startpos+s.loopstart;
- c.loopend=c.startpos+s.loopend;
- c.samprate=s.samprate;
- c.redlev=s.redlev;
- c.smpptr=s.ptr;
- c.mode=0;
- if (bit16)
- c.mode|=0x04;
- c.cursamp=c.nextsample;
- c.orgloop=0;
- if (s.type&mcpSampLoop)
- {
- c.orgloop=1;
- c.mode|=0x08;
- if (s.type&mcpSampBiDi)
- c.mode|=0x10;
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- }
- else
- {
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- }
- }
- if (c.nextpos!=-1)
- {
- unsigned long pos=c.startpos+(c.nextpos>>c.redlev);
- if (c.mode&0x08)
- {
- if (pos>=c.loopend)
- pos=c.loopstart+(pos-c.loopstart)%(c.loopend-c.loopstart);
- }
- else
- if (pos>=c.endpos)
- pos=c.endpos-1;
- setpoint8(pos, 0);
- setmode(c.mode|(getmode()&0x40));
- }
- if (c.loopchange!=-1)
- {
- if (c.loopchange&&c.orgloop)
- c.mode|=0x08;
- else
- c.mode&=~0x08;
- setmode(c.mode|(getmode()&0x40));
- if (c.mode&0x08)
- {
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- }
- else
- {
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- }
- }
- if (!(getmode()&1))
- {
- short v,p;
- v=c.voll+c.volr;
- if (v)
- setpan((15*c.volr+v/2)/v);
- fadevol(c.pause?0:linvol[v]);
- setfreq(muldiv64(muldiv64(c.orgfreq, c.samprate*masterfreq, c.orgdiv), activevoices, 154350));
- }
- else
- fadevoldown();
- }
- else
- fadevoldown();
-
- c.nextsample=-1;
- c.nextpos=-1;
- c.loopchange=-1;
- }
-
- playerproc();
-
- stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
- gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
- }
-
- static void processtickdc()
- {
- int i;
-
- for (i=0; i<channelnum; i++)
- {
- guschan &c=channels[i];
- if (c.inited&&(c.chstatus||(c.nextpos!=-1)))
- {
- selvoc(2*i);
- setmode(c.mode|3);
- fadevoldown();
- selvoc(2*i+1);
- setmode(c.mode|3);
- fadevoldown();
- }
-
- c.chstatus=0;
- }
-
- for (i=0; i<channelnum; i++)
- {
- selvoc(2*i);
- while (!(getvmode()&1));
- selvoc(2*i+1);
- while (!(getvmode()&1));
- }
-
- for (i=0; i<channelnum; i++)
- {
- guschan &c=channels[i];
- if (c.inited)
- {
- if (c.nextsample!=-1)
- {
- gussample &s=samples[c.nextsample];
- unsigned char bit16=!!(s.type&mcpSamp16Bit);
- c.startpos=s.pos;
- if (bit16)
- c.startpos=(c.startpos&0xC0000)|((c.startpos>>1)&0x1FFFF)|0x20000;
- c.endpos=c.startpos+s.length;
- c.loopstart=c.startpos+s.loopstart;
- c.loopend=c.startpos+s.loopend;
- c.samprate=s.samprate;
- c.redlev=s.redlev;
- c.smpptr=s.ptr;
- c.mode=0;
- if (bit16)
- c.mode|=0x04;
- c.cursamp=c.nextsample;
- c.orgloop=0;
- if (s.type&mcpSampLoop)
- {
- c.orgloop=1;
- c.mode|=0x08;
- if (s.type&mcpSampBiDi)
- c.mode|=0x10;
- selvoc(2*i);
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- selvoc(2*i+1);
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- }
- else
- {
- selvoc(2*i);
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- selvoc(2*i+1);
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- }
- }
- if (c.nextpos!=-1)
- {
- unsigned long pos=c.startpos+(c.nextpos>>c.redlev);
- if (c.mode&0x08)
- {
- if (pos>=c.loopend)
- pos=c.loopstart+(pos-c.loopstart)%(c.loopend-c.loopstart);
- }
- else
- if (pos>=c.endpos)
- pos=c.endpos;
- selvoc(2*i);
- setpoint8(pos, 0);
- selvoc(2*i+1);
- setpoint8(pos, 0);
- selvoc(2*i);
- setmode(c.mode|(getmode()&0x40));
- selvoc(2*i+1);
- setmode(c.mode|(getmode()&0x40));
- }
- if (c.loopchange!=-1)
- {
- if (c.loopchange&&c.orgloop)
- c.mode|=0x08;
- else
- c.mode&=~0x08;
- selvoc(2*i);
- setmode(c.mode|(getmode()&0x40));
- if (c.mode&0x08)
- {
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- }
- else
- {
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- }
- selvoc(2*i+1);
- setmode(c.mode|(getmode()&0x40));
- if (c.mode&0x08)
- {
- setpoint8(c.loopstart, 1);
- setpoint8(c.loopend, 2);
- }
- else
- {
- setpoint8(c.startpos, 1);
- setpoint8(c.endpos, 2);
- }
- }
- selvoc(2*i);
- if (!(getmode()&1))
- {
- unsigned long frq=muldiv64(muldiv64(c.orgfreq, c.samprate*masterfreq, c.orgdiv), activevoices, 154350);
- selvoc(2*i);
- setfreq(frq);
- fadevol(c.pause?0:linvol[c.voll]);
- selvoc(2*i+1);
- setfreq(frq);
- fadevol(c.pause?0:linvol[c.volr]);
- }
- else
- {
- selvoc(2*i);
- fadevoldown();
- selvoc(2*i+1);
- fadevoldown();
- }
- }
- else
- {
- selvoc(2*i);
- fadevoldown();
- selvoc(2*i+1);
- fadevoldown();
- }
-
- c.nextsample=-1;
- c.nextpos=-1;
- c.loopchange=-1;
- }
-
- playerproc();
-
- stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
- gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
- }
-
- unsigned long doupload8(const void *buf, unsigned long guspos, unsigned long maxlen, unsigned short port);
- #pragma aux doupload8 parm [esi] [ebx] [ecx] [edx] modify [eax] value [ebx] = \
- "pushf" \
- "cli" \
- "add dx,103h" \
- "mov al,44h" \
- "out dx,al" \
- "add dx,2" \
- "mov eax,ebx" \
- "shr eax,16" \
- "out dx,al" \
- "sub dx,2" \
- "mov al,43h" \
- "out dx,al" \
- "inc dx" \
- "lp:" \
- "mov ax,bx" \
- "out dx,ax" \
- "mov al,[esi]" \
- "add dx,3" \
- "out dx,al" \
- "sub dx,3" \
- "inc ebx" \
- "inc esi" \
- "test bl,bl" \
- "loopnz lp" \
- "popf"
-
- unsigned long doupload16(const void *buf, unsigned long guspos, unsigned long maxlen, unsigned short port);
- #pragma aux doupload16 parm [esi] [ebx] [ecx] [edx] modify [eax] value [ebx] = \
- "pushf" \
- "cli" \
- "add dx,103h" \
- "mov al,44h" \
- "out dx,al" \
- "add dx,2" \
- "mov eax,ebx" \
- "shr eax,16" \
- "out dx,al" \
- "sub dx,2" \
- "mov al,43h" \
- "out dx,al" \
- "inc dx" \
- "shr ecx,1" \
- "lp:" \
- "mov ax,bx" \
- "out dx,ax" \
- "mov al,[esi]" \
- "add dx,3" \
- "out dx,al" \
- "sub dx,3" \
- "inc ebx" \
- "mov ax,bx" \
- "out dx,ax" \
- "mov al,[esi+1]" \
- "add dx,3" \
- "out dx,al" \
- "sub dx,3" \
- "inc ebx" \
- "add esi,2" \
- "test bl,bl" \
- "loopnz lp" \
- "popf"
-
- static void dmaupload()
- {
- int upbytes;
- if (dmapos&31)
- {
- upbytes=(-dmapos)&31;
- if (upbytes>dmaleft)
- upbytes=dmaleft;
- if (!dma16bit)
- doupload8(dmaxfer, dmapos, upbytes, gusPort);
- else
- doupload16(dmaxfer, dmapos, upbytes, gusPort);
- dmaxfer=((char*)dmaxfer)+upbytes;
- dmaleft-=upbytes;
- dmapos+=upbytes;
- }
- if (!dmaleft)
- {
- dmaactive=0;
- return;
- }
- upbytes=dmaleft;
- if (upbytes>dmalen)
- upbytes=dmalen;
- if (((dmapos+upbytes)&0xC0000)>(dmapos&0xC0000))
- upbytes=0x40000-(dmapos&0x3FFFF);
-
- dmaactive=1;
- unsigned short adr=dmapos>>4;
- if (gusDMA&4)
- adr=(adr&0xC000)|((adr&0x3FFF)>>1);
- outGUS(0x41, 0);
- memcpy(dmabuf, dmaxfer, upbytes);
- dmaStart(gusDMA, dmabuf, upbytes, 0x08);
- dmaxfer=((char*)dmaxfer)+upbytes;
- dmaleft-=upbytes;
- dmapos+=upbytes;
- outwGUS(0x42, adr);
- outGUS(0x41, (gusDMA&4)|0x21|(dma16bit?0x40:0x00));
- }
-
- static void slowupload()
- {
- unsigned long endpos=dmapos+dmaleft;
- unsigned long stpos=dmapos;
- if (!dma16bit)
- while (dmapos<endpos)
- dmapos=doupload8((char*)dmaxfer+dmapos-stpos, dmapos, endpos-dmapos, gusPort);
- else
- while (dmapos<endpos)
- dmapos=doupload16((char*)dmaxfer+dmapos-stpos, dmapos, endpos-dmapos, gusPort);
- }
-
- static void handle_voice()
- {
- /*
- unsigned long wave_ignore=0;
- unsigned long volume_ignore=0;
-
- while (1)
- {
- unsigned char irq_source=inGUS(0x8F);
-
- unsigned char voice=irq_source&0x1F;
-
- if ((irq_source&0xC0)==0xC0)
- break;
-
- unsigned long voice_bit=1<<voice;
-
- if (!(irq_source&0x80))
- if (!(wave_ignore&voice_bit))
- {
- selvoc(voice);
- if (!((inGUS(0x80)&0x08)||(inGUS(0x8D)&0x04)))
- wave_ignore|=voice_bit;
- }
- if (!(irq_source&0x40))
- if (!(volume_ignore&voice_bit))
- {
- selvoc(voice);
- if (!(inGUS(0x8D)&0x08))
- volume_ignore|=voice_bit;
- }
- }
- */
- }
-
- static void irqrout()
- {
- while (1)
- {
- unsigned char source=inpGUS(0x6);
- if (!source)
- break;
- if (source&0x03)
- inpGUS(0x100);
- if (source&0x80)
- if (inGUS(0x41)&0x40)
- dmaupload();
- if (source&0x04)
- {
- if (!usesystimer&&!paused)
- {
- if (gtimerpos<=256)
- gtimerpos=gtimerlen;
- else
- gtimerpos-=256;
- settimer(0x00);
- settimerlen((gtimerpos<=256)?(256-gtimerpos):0);
- settimer(0x04);
- if (gtimerpos==gtimerlen)
- if (doublechan)
- processtickdc();
- else
- processtick();
- }
- else
- {
- settimer(0x00);
- settimer(0x04);
- }
- }
- if (source&0x08)
- {
- settimer(0x00);
- settimer(0x04);
- }
- if (source&0x60)
- handle_voice();
- }
- }
-
- static void timerrout()
- {
- if (paused)
- return;
- if (stimerpos<=65536)
- stimerpos=stimerlen;
- else
- stimerpos-=65536;
- tmSetNewRate((stimerpos<=65536)?stimerpos:65536);
- if (stimerpos==stimerlen)
- if (doublechan)
- processtickdc();
- else
- processtick();
- }
-
- void stackcall(void *);
- #pragma aux stackcall parm [eax] = \
- "mov word ptr oldssesp+4,ss" \
- "mov dword ptr oldssesp+0,esp" \
- "lss esp,stack" \
- "sti" \
- "call eax" \
- "cli" \
- "lss esp,oldssesp"
-
- static void stackirq()
- {
- if (stackused)
- return;
- stackused++;
- stackcall(irqrout);
- stackused--;
- }
-
- static void stacktimer()
- {
- if (stackused)
- return;
- stackused++;
- stackcall(timerrout);
- stackused--;
- }
-
- static void voidtimer()
- {
- }
-
- static void calcvols(guschan &c)
- {
- short vl=(c.orgvol*mastervol/16)*amplify/65536;
- if (vl>=0x200)
- vl=0x1FF;
- short vr=(vl*((c.orgpan*masterpan/64)+0x80))>>8;
- vl-=vr;
-
- if (masterbal)
- if (masterbal<0)
- vr=(vr*(64+masterbal))>>6;
- else
- vl=(vl*(64-masterbal))>>6;
- c.voll=vl;
- c.volr=vr;
- }
-
- static int LoadSamples(sampleinfo *sil, int n)
- {
- if (n>MAXSAMPLES)
- return 0;
-
- if (!mcpReduceSamples(sil, n, gusMem, mcpRedGUS))
- return 0;
-
- if (!doslowupload)
- irqInit(gusIRQ, stackirq, 1);
-
- mempos=0;
- int i;
- for (i=0; i<(2*n); i++)
- {
- sampleinfo &si=sil[i%n];
- if ((!!(si.type&mcpSamp16Bit))^(i<n))
- continue;
- gussample &s=samples[i%n];
- s.length=si.length;
- s.loopstart=si.loopstart;
- s.loopend=si.loopend;
- s.samprate=si.samprate;
- s.type=si.type;
- int bit16=!!(si.type&mcpSamp16Bit);
- s.redlev=(si.type&mcpSampRedRate4)?2:(si.type&mcpSampRedRate2)?1:0;
- s.pos=mempos;
- mempos+=(s.length+2)<<bit16;
-
- if (s.loopstart==s.loopend)
- s.type&=~mcpSampLoop;
-
- dma16bit=bit16;
- dmaleft=(s.length+2)<<dma16bit;
- dmaxfer=si.ptr;
- dmapos=s.pos;
- if (doslowupload)
- {
- slowupload();
- continue;
- }
-
- dmaupload();
- unsigned long t0=clock();
- while ((t0+(int)CLK_TCK*2)>clock())
- if (!dmaactive)
- break;
- if (!dmaactive)
- continue;
-
- irqClose();
- doslowupload=1;
- dmaactive=0;
-
- dma16bit=bit16;
- dmaleft=(s.length+2)<<dma16bit;
- dmaxfer=si.ptr;
- dmapos=s.pos;
- slowupload();
- }
-
- if (!doslowupload)
- irqClose();
-
- samplenum=n;
- // smSamplesTo8(sil, n);
-
- for (i=0; i<n; i++)
- samples[i].ptr=sil[i].ptr;
-
- return 1;
- }
-
-
-
-
-
- static int OpenPlayer(int chan, void (*proc)())
- {
- if (chan>32)
- chan=32;
-
- mixSetChan(chan);
-
- orgspeed=50*256;
-
- memset(channels, 0, sizeof(guschan)*chan);
- playerproc=proc;
- doublechan=chan<8;
- int i;
- if (doublechan)
- {
- initgus(2*chan);
- for (i=0; i<chan; i++)
- {
- selvoc(2*i);
- setpan(0);
- selvoc(2*i+1);
- setpan(15);
- }
- }
- else
- initgus(chan);
- channelnum=chan;
-
- selvoc(0);
- delayGUS();
- outpGUS0(0x09);
- delayGUS();
-
-
- if (usesystimer)
- {
- stimerlen=muldiv64(256, 1193046*256, orgspeed*relspeed);
- stimerpos=stimerlen;
- tmInit(stacktimer, (stimerpos<=65536)?stimerpos:65536);
- }
- else
- {
- irqInit(gusIRQ, stackirq, 1);
- gtimerlen=muldiv64(256, 12500*256, orgspeed*relspeed);
- gtimerpos=gtimerlen;
- settimerlen((gtimerpos<=256)?(256-gtimerpos):0);
- settimer(0x04);
-
- tmInit(voidtimer, 65536);
- }
- outpGUS8(0x04);
- outpGUS9(0x01);
-
- mcpNChan=chan;
-
- return 1;
- }
-
- static void ClosePlayer()
- {
- mcpNChan=0;
-
- tmClose();
- if (!usesystimer)
- irqClose();
-
- initgus(14);
- channelnum=0;
- }
-
- unsigned short _disableint();
- void _restoreint(unsigned short);
- #pragma aux _disableint value [ax] = "pushf" "pop ax" "cli"
- #pragma aux _restoreint parm [ax] = "push ax" "popf"
-
- static void SetSpeed(unsigned long s)
- {
- orgspeed=s;
- }
-
- static void SetFilter(unsigned char f)
- {
- filter=f%8;
- }
-
- static void SetMasterVol(unsigned char vol)
- {
- mastervol=vol;
- int i;
- for (i=0; i<channelnum; i++)
- calcvols(channels[i]);
- }
-
- static void SetMasterPan(signed char pan)
- {
- masterpan=pan;
- int i;
- for (i=0; i<channelnum; i++)
- calcvols(channels[i]);
- }
-
- static void SetMasterBal(signed char bal)
- {
- masterbal=bal;
- int i;
- for (i=0; i<channelnum; i++)
- calcvols(channels[i]);
- }
-
- static void SetMasterSpeed(unsigned short sp)
- {
- if (sp<16)
- sp=16;
- relspeed=sp;
- }
-
- static void SetMasterFreq(unsigned short p)
- {
- masterfreq=p;
- }
-
- static void SetAmplify(unsigned long amp)
- {
- amplify=amp;
- int i;
- for (i=0; i<channelnum; i++)
- calcvols(channels[i]);
- mixSetAmplify(amp);
- }
-
-
- static void SetInstr(unsigned char ch, unsigned short samp)
- {
- channels[ch].chstatus=1;
- channels[ch].nextsample=samp;
- channels[ch].loopchange=1;
- channels[ch].inited=1;
- }
-
-
-
- static void GetMixChannel(int ch, mixchannel &chn, int rate)
- {
- chn.status=0;
-
- unsigned short is=_disableint();
- selvoc(doublechan?2*ch:ch);
- unsigned long pos=getpoint8(0);
- unsigned char mode=getmode();
- _restoreint(is);
- guschan &c=channels[ch];
-
- if ((paused&&!c.wasplaying)||(!paused&&(mode&1))||!c.inited)
- return;
-
- if (c.pause)
- chn.status|=MIX_MUTE;
-
- unsigned short resvoll,resvolr;
- resvoll=c.voll;
- resvolr=c.volr;
-
- chn.vols[0]=resvoll*4096/amplify;
- chn.vols[1]=resvolr*4096/amplify;
- chn.status|=((mode&0x08)?MIX_LOOPED:0)|((mode&0x10)?MIX_PINGPONGLOOP:0)|((mode&0x04)?MIX_PLAY16BIT:0);
- chn.step=muldiv64(muldiv64(muldiv64(c.orgfreq, masterfreq, 256), c.samprate, c.orgdiv), 1<<16, rate);
- if (mode&0x40)
- chn.step=-chn.step;
- chn.samp=c.smpptr;
- chn.length=c.endpos-c.startpos;
- chn.loopstart=c.loopstart-c.startpos;
- chn.loopend=c.loopend-c.startpos;
- chn.fpos=pos<<7;
- chn.pos=((pos>>9)&0xFFFFF)-c.startpos;
- if (filter>=6)
- chn.status|=MIX_INTERPOLATE;
- chn.status|=MIX_PLAYING;
- }
-
-
-
- static void SetVolume(unsigned char ch, signed short v)
- {
- if (v>=0x100)
- v=0x100;
- if (v<0)
- v=0;
- channels[ch].orgvol=v;
- calcvols(channels[ch]);
- }
-
- static void SetPan(unsigned char ch, signed short p)
- {
- if (p>=0x80)
- p=0x80;
- if (p<=-0x80)
- p=-0x80;
- channels[ch].orgpan=p;
- calcvols(channels[ch]);
- }
-
- static void SetReverbChorus(unsigned char ch, unsigned char reverb, unsigned char chorus)
- {
- }
-
- static void SetPos(unsigned char ch, unsigned long pos)
- {
- channels[ch].nextpos=pos;
- }
-
- static void SetFreq(unsigned char ch, unsigned long frq, unsigned long div)
- {
- channels[ch].orgfreq=frq;
- channels[ch].orgdiv=div;
- }
-
- static void SetFreqLog(unsigned char ch, signed short note)
- {
- channels[ch].orgfreq=8363;
- channels[ch].orgdiv=mcpGetFreq8363(-note);
- }
-
- static void Play(unsigned char ch, unsigned long frq, unsigned long div)
- {
- channels[ch].orgfreq=frq;
- channels[ch].orgdiv=div;
- channels[ch].nextpos=0;
- channels[ch].loopchange=1;
- }
-
- static void PlayLog(unsigned char ch, signed short note)
- {
- Play(ch, 8363, mcpGetFreq8363(-note));
- }
-
- static void Stop(unsigned char ch)
- {
- channels[ch].nextpos=-1;
- channels[ch].chstatus=1;
- }
-
- static void LeaveLoop(unsigned char ch)
- {
- channels[ch].loopchange=0;
- }
-
- static void Reset(unsigned char ch)
- {
- unsigned char p=channels[ch].pause;
- memset(channels+ch, 0, sizeof(guschan));
- channels[ch].pause=p;
- }
-
- static void Pause(unsigned char p)
- {
- if (p==paused)
- return;
- int i;
- if (paused)
- {
- for (i=0; i<channelnum; i++)
- if (doublechan)
- {
- if (channels[i].wasplaying)
- {
- selvoc(2*i);
- setmode(channels[i].mode|(getmode()&0x40));
- selvoc(2*i+1);
- setmode(channels[i].mode|(getmode()&0x40));
- }
- }
- else
- if (channels[i].wasplaying)
- {
- selvoc(i);
- setmode(channels[i].mode|(getmode()&0x40));
- }
- gtimerpos=0;
- stimerpos=0;
- paused=0;
- if (!usesystimer)
- settimer(0x04);
- }
- else
- {
- paused=1;
- if (!usesystimer)
- settimer(0x00);
- for (i=0; i<channelnum; i++)
- if (doublechan)
- {
- selvoc(2*i);
- channels[i].wasplaying=!(getmode()&1);
- setmode(3|(getmode()&0x40));
- selvoc(2*i+1);
- setmode(3|(getmode()&0x40));
- }
- else
- {
- selvoc(i);
- channels[i].wasplaying=!(getmode()&1);
- setmode(3|(getmode()&0x40));
- }
- }
- }
-
- static int GetStatus(int ch)
- {
- unsigned is=_disableint();
- selvoc(doublechan?2*ch:ch);
- int rv=!(getmode()&1);
- if (paused&&channels[ch].wasplaying)
- rv=1;
- _restoreint(is);
- return rv;
- }
-
- static void SET(int ch, int opt, int val)
- {
- switch (opt)
- {
- case mcpGSpeed:
- SetSpeed(val);
- break;
- case mcpCInstrument:
- SetInstr(ch, val);
- break;
- case mcpCMute:
- channels[ch].pause=val;
- break;
- case mcpCStatus:
- if (!val)
- Stop(ch);
- break;
- case mcpCReset:
- Reset(ch);
- break;
- case mcpCVolume:
- SetVolume(ch, val);
- break;
- case mcpCPanning:
- SetPan(ch, val);
- break;
- case mcpMasterAmplify:
- SetAmplify(val);
- break;
- case mcpMasterPause:
- Pause(val);
- break;
- case mcpCPosition:
- SetPos(ch, val);
- break;
- case mcpCPitch:
- SetFreqLog(ch, val);
- break;
- case mcpCPitchFix:
- SetFreq(ch, val, 0x10000);
- break;
- case mcpCPitch6848:
- SetFreq(ch, 6848, val);
- break;
- case mcpMasterVolume:
- SetMasterVol(val);
- break;
- case mcpMasterPanning:
- SetMasterPan(val);
- break;
- case mcpMasterBalance:
- SetMasterBal(val);
- break;
- case mcpMasterSpeed:
- SetMasterSpeed(val);
- break;
- case mcpMasterPitch:
- SetMasterFreq(val);
- break;
- case mcpMasterFilter:
- SetFilter(val);
- break;
- }
- }
-
- static int GET(int ch, int opt)
- {
- switch (opt)
- {
- case mcpCStatus:
- return !!GetStatus(ch);
- case mcpCMute:
- return !!channels[ch].pause;
- case mcpGTimer:
- return tmGetTimer();
- }
- return 0;
- }
-
-
-
-
-
-
-
-
- static int initu(const deviceinfo &c)
- {
- doslowupload=(c.opt&SS_GUS_SLOWUPLOAD)||(c.dma==-1)||(c.irq==-1);
- usesystimer=(c.opt&SS_GUS_SYSTIMER)||(c.irq==-1);
-
- dmaactive=0;
- dmalen=32768;
- dmabuf=dmaAlloc(dmalen, dmasel);
- dmalen&=~31;
- stack=new char [stacksize];
- if (!stack||!dmabuf)
- return 0;
- stack+=stacksize;
- stackused=0;
-
- if (!mixInit(GetMixChannel, 1))
- return 0;
-
- int i;
-
- if (!testPort(c.port))
- return 0;
-
- gusPort=c.port;
- gusIRQ=c.irq;
- gusDMA=c.dma;
- // gusIRQ2=c.irq2;
- gusDMA2=c.dma2;
-
- channelnum=0;
- filter=0;
-
- initgus(14);
-
- relspeed=256;
- paused=0;
-
- mastervol=64;
- masterpan=64;
- masterbal=0;
- masterfreq=256;
- amplify=65536;
-
- linvol[0]=0;
- linvol[512]=0x0FFF;
- for (i=1; i<512; i++)
- {
- int j,k;
- k=i;
- for (j=0x0600; k; j+=0x0100)
- k>>=1;
- linvol[i]=j|((i<<(8-((j-0x700)>>8)))&0xFF);
- }
-
- mcpLoadSamples=LoadSamples;
- mcpOpenPlayer=OpenPlayer;
- mcpClosePlayer=ClosePlayer;
- mcpSet=SET;
- mcpGet=GET;
-
- return 1;
- }
-
-
- static void closeu()
- {
- mcpOpenPlayer=0;
- mixClose();
- dmaFree(dmasel);
- delete (char near *)(stack-stacksize);
- }
-
- static int detectu(deviceinfo &c)
- {
- if (!getcfg())
- {
- if (c.port==-1)
- return 0;
- gusPort=c.port;
- gusIRQ=c.irq;
- // gusIRQ2=(c.irq2==-1)?c.irq:c.irq2;
- gusDMA=c.dma;
- gusDMA2=(c.dma2==-1)?c.dma:c.dma2;
- }
- else
- {
- if (c.port!=-1)
- gusPort=c.port;
- if (c.irq!=-1)
- gusIRQ=c.irq;
- // if (c.irq2!=-1)
- // gusIRQ2=c.irq2;
- if (c.dma!=-1)
- gusDMA=c.dma;
- if (c.dma2!=-1)
- gusDMA2=c.dma2;
- }
-
- if (!testPort(gusPort))
- return 0;
- c.subtype=-1;
- c.dev=&mcpUltraSound;
- c.port=gusPort;
- c.port2=-1;
- // c.irq=(gusIRQ<gusIRQ2)?gusIRQ:gusIRQ2;
- // c.irq2=(gusIRQ<gusIRQ2)?gusIRQ2:gusIRQ;
- c.irq=gusIRQ;
- // c.irq2=gusIRQ2;
- c.irq2=-1;
- c.dma=gusDMA;
- c.dma2=gusDMA2;
- if ((c.opt&SS_GUS_SLOWUPLOAD)&&(c.opt&SS_GUS_SYSTIMER))
- c.irq=-1;
- if ((c.opt&SS_GUS_SLOWUPLOAD)||(c.irq==-1))
- {
- c.dma=-1;
- c.dma2=-1;
- }
- c.mem=gusMem;
- c.chan=32;
- return 1;
- }
-
- extern "C" sounddevice mcpUltraSound={SS_WAVETABLE, "Gravis UltraSound", detectu, initu, closeu};
-
- #include "devigen.h"
- #include "psetting.h"
-
- static unsigned long gusGetOpt(const char *sec)
- {
- unsigned long opt=0;
- if (cfGetProfileBool(sec, "gusslowupload", 1, 1))
- opt|=SS_GUS_SLOWUPLOAD;
- if (cfGetProfileBool(sec, "gussystemtimer", 1, 1))
- opt|=SS_GUS_SYSTIMER;
- return opt;
- }
-
- extern "C" devaddstruct mcpGUSAdd = {gusGetOpt, 0, 0, 0};
-